home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / pascal / totdoc.zip / CHAPT3.TXT < prev    next >
Text File  |  1991-02-11  |  49KB  |  1,059 lines

  1.                                                                   Toolkit Basics
  2.  
  3.  
  4.  
  5.          "No, what I said was 'No new taxis'"        Georgio Bush, 1990
  6.  
  7.  
  8.  
  9.  
  10. An Object Primer
  11.  
  12.          Let's talk cars. We all know that you don't need to be a combustion
  13.          mechanic to drive a car (that's a veeehickle if you're from Texas), but
  14.          most good drivers know a few basic principles about how a car works.
  15.          The same philosophy is true for object oriented programming: you don't
  16.          need to be an OOP guru to use the Toolkit but a little understanding is
  17.          helpful. The modest goal of this section is to explain some of the
  18.          object oriented principles to help you get up and running with the
  19.          Toolkit as soon as possible. Over time, you will gain OOP expertise
  20.          without even trying! If you are already familiar with OOP, skip to the
  21.          next section.
  22.          For now, we will concentrate on those aspects of OOP you will need in
  23.          order to understand how to use the Toolkit. In Part 2: Extending the
  24.          Toolkit, the more advanced concepts of inheritance and extensibility
  25.          are addressed.
  26.  
  27.  
  28.          In plain Pascal, there are types like integer, real, string, etc. and
  29.          you declare variables to be of a specific type. You can even define new
  30.          types. For example, the following declaration defines a new type
  31.          Address:
  32.  
  33.                   TYPE
  34.                   Address = record
  35.                      Name: string[20];
  36.                      Street: string[30];
  37.                      CityStZip: string[20];
  38.                   end;
  39.  
  40.          Having defined the type Address, you can then create variables of this
  41.          type, e.g.
  42.  
  43.                   VAR
  44.                   BobsHouse: Address;
  45.  
  46.          In most programs, you will write procedures and functions that can
  47.          manipulate the data stored in these variables, e.g.
  48.  
  49.                   procedure PrintLabel(Addr: address);
  50.                   function  Zip(Addr:address): string;
  51.  
  52.  
  53.  
  54. 3-2                                                                 User's Guide
  55. --------------------------------------------------------------------------------
  56.  
  57.          But most of you know this stuff anyway. Things aren't so very different
  58.          with OOP. The primary difference is that, with OOP, the data and the
  59.          procedures and functions which manipulate the data are combined into a
  60.          single type, called an object. This concept of combining data and
  61.          procedures/functions is referred to as encapsulation. Listed below is a
  62.          way to create an object type called AddressOBJ:
  63.  
  64.                   TYPE
  65.                   AddressOBJ = object
  66.                      Name: string[20];
  67.                      Street: string[30];
  68.                      CityStZip: string[20];
  69.                      {methods ...}
  70.                      procedure PrintLabel;
  71.                      function  Zip: string;
  72.                   end; {object}
  73.  
  74.                   VAR
  75.                   BobsHouse: AddressOBJ;
  76.  
  77.          Notice that the object type declaration is very similar to a record
  78.          declaration, but the keyword object is used instead of record. The
  79.          procedure and function declaration are included in the object declara-
  80.          tion, and are referred to (in OOP nomenclature) as methods. The methods
  81.          are not passed the address record as a parameter, because the procedure
  82.          and functions in an object can directly access the data in the object,
  83.          and so don't need to be passed the data. The "variable" BobsHouse,
  84.          which is of type AddressOBJ, is referred to as an instance - in other
  85.          words, object variables are called instances! All object type declara-
  86.          tions in the Toolkit end with the characters "OBJ".
  87.  
  88.          The individual elements of an object (just like a record) can be
  89.          accessed by using the "dot" notation. For example, to print a label,
  90.          you would use the following statement:
  91.                   BobsHouse.PrintLabel
  92.  
  93.  
  94.          You can also use the "with identifier do" shortcut, e.g.
  95.                   with BobsHouse do
  96.                   begin
  97.                      PrintLabel
  98.                      .....
  99.                   end; {with}
  100.  
  101.  
  102.          In theory, you could also access the data elements using the dot
  103.          method, e.g. BobsHouse.Street := '12 Paradise Drive', but you
  104.          shouldn't! While it is syntactically correct and will compile, this is
  105.          bad practice. A basic precept of encapsulation is that you never access
  106.  
  107.  
  108. Toolkit Basics                                                               3-3
  109. --------------------------------------------------------------------------------
  110.  
  111.          the data elements of an instance directly. You should create methods
  112.          within the object to access the object's data. In the above example,
  113.          there is no way to access the data in the object (other than breaking
  114.          the rules) so a data update method would need to be created. Listed
  115.          below is an improved type declaration of the AddressOBJ:
  116.  
  117.                   TYPE
  118.                   AddressOBJ = object
  119.                      Name: string[20];
  120.                      Street: string[30];
  121.                      CityStZip: string[20];
  122.                      {methods ...}
  123.                      procedure Adddata(Nam,St,Ci,St,Zp:string);
  124.                      procedure PrintLabel;
  125.                      function  Zip: string;
  126.                   end; {object}
  127.  
  128.          The new AddData method would be used to set the values of the Name,
  129.          Street and CityStZip elements. For example, the following two state-
  130.          ments would print the label:
  131.  
  132.                   with BobsHouse do
  133.                   begin
  134.                      AddData('Bobbo','12 Paradise Drive',
  135.                              'Dome','TX','77186');
  136.                      Printlabel;
  137.                   end;
  138.  
  139.          If you are curious, each method identified in an object must be
  140.          included in the body of the program or unit. For example, later in the
  141.          program there might be the following method definition:
  142.  
  143.                   ...
  144.  
  145.                   procedure AddressOBJ.Adddata(Nam,St,Ci,St,Zp:string);
  146.                   {}
  147.                   begin
  148.                      Name := copy(Nam,1,20);
  149.                      Street := copy(St,1,30);
  150.                      ...
  151.                   end; {of proc}
  152.  
  153.                   ...
  154.  
  155.          Now, back to the main discussion. The advantage of using methods to
  156.          access the object data is that the object user (that's you) does not
  157.          need to know or care about how the data is stored within the object.
  158.          The internal data structure might be modified at some stage to use
  159.  
  160.  
  161.  
  162. 3-4                                                                 User's Guide
  163. --------------------------------------------------------------------------------
  164.  
  165.          pointers or to store ASCIIZ strings, etc, but the same method AddData
  166.          can still be called in the same way as previously. What Adddata does
  167.          (behind the scenes) may have changed, but your program still compiles
  168.          and runs without modification.
  169.  
  170.          For various reasons, many objects need to be initialized before they
  171.          can be used. For example, some memory may need to be allocated on the
  172.          heap. When you have finished with such an object, the memory will need
  173.          to be disposed of. Just because the procedure in which you declared an
  174.          object instance (i.e. variable) has terminated, it does not necessarily
  175.          mean that the object data has been removed.
  176.          Although not mandatory, a de facto OOP standard is to have two special
  177.          methods for all objects. Namely, INIT and DONE. These special methods
  178.          are used to initialize an object and dispose of an object, respec-
  179.          tively. Throughout the Toolkit, every object has INIT and DONE methods.
  180.          Always call INIT before any other object methods, and always call DONE
  181.          when you have finished with an object. In some instances the INIT
  182.          method may require some parameters.
  183.  
  184.          In our example, the object is useless if no data has been assigned.
  185.          Adopting the new convention, it might be more appropriate to rename the
  186.          AddData method INIT, since you will always want to assign values before
  187.          calling other object methods. We should also add a DONE method which
  188.          will provide a way of disposing of any dynamic data we might incorpo-
  189.          rate at a later stage. The revised object declaration would be as fol-
  190.          lows:
  191.                   TYPE
  192.                   AddressOBJ = object
  193.                      Name: string[20]
  194.                      Street: string[30]
  195.                      CityStZip: string[20]
  196.                      {methods ...}
  197.                      procedure Init(Nam,St,Ci,St,Zp:string);
  198.                      procedure PrintLabel;
  199.                      function  Zip: string;
  200.                      procedure Done;
  201.                   end; {object}
  202.  
  203.  
  204.          For now, the DONE procedure will probably be empty, i.e. it performs no
  205.          action. This is referred to as an abstract method. The following code
  206.          fragment shows how to use this revised object:
  207.                   with BobsHouse do
  208.                   begin
  209.                      Init('Bobbo','12 Paradise Drive','Dome','TX','77186');
  210.                      Printlabel;
  211.                      Done;
  212.                   end;
  213.  
  214.  
  215.  
  216. Toolkit Basics                                                               3-5
  217. --------------------------------------------------------------------------------
  218.  
  219.          Note: there is an even more compelling reason to have INIT and DONE
  220.          methods. One of the most powerful features of OOP is polymorphism,
  221.          which allows you to declare virtual methods (discussed in part 2). In
  222.          general, objects which use virtual methods must have a constructor and
  223.          a destructor, and these are normally called INIT and DONE.
  224.  
  225.  
  226.          To recap, the following key points should be remembered:
  227.  
  228.          q     All Toolkit objects end with the characters OBJ.
  229.          q     Use the "dot" notation to access object methods.
  230.  
  231.          q     When using the Toolkit always initialize an instance with INIT,
  232.                and dispose of it with DONE.
  233.  
  234.  
  235.          Having covered the OOP basics as they relate to the Toolkit, it is
  236.          worthwhile reviewing the message demo program that was discussed in
  237.          chapter 2:
  238.  
  239.                  program DemoMessage1;
  240.                  {demms1}
  241.  
  242.                  Uses DOS, CRT,
  243.                       totFAST, totMSG;
  244.                  Var  MsgWin : MessageOBJ;
  245.  
  246.                  begin
  247.                     Screen.Clear(white,'░'); {paint the screen}
  248.                     with MsgWin do
  249.                     begin
  250.                        Init(1,' Message ');
  251.                        AddLine('');
  252.                        AddLine('The message unit provides a');
  253.                        AddLine('very easy way of displaying');
  254.                        AddLine('pop-up messages in a move-');
  255.                        AddLine('able window.');
  256.                        AddLine('');
  257.                        Show;
  258.                        Done;
  259.                     end;
  260.                  end.
  261.  
  262.          Hopefully, the statements make more sense now!
  263.  
  264.  
  265.  
  266. 3-6                                                                 User's Guide
  267. --------------------------------------------------------------------------------
  268.  
  269.          "So what?" and "Why bother?" you may ask. It is not appropriate, at
  270.          this stage, to explore the advantages of encapsulation. Just use the
  271.          Toolkit a little, and you will see what can be done with OOP! We have
  272.          covered everything you need to know about OOP to use the  Toolkit (and
  273.          then some), but as a programmer it is always good to explore "under the
  274.          hood". A great way to learn practical insights into OOP is to explore
  275.          the Toolkit source code. When you are ready to extend the Toolkit to
  276.          meet your specific needs, refer to Part 2. Also, read some of the OOP
  277.          literature in magazines and books - OOP is here to stay.
  278.  
  279.          Meanwhile, be happy with the "how" for now. The "why" will become all
  280.          too clear in time.
  281.  
  282.  
  283. Building the Toolkit TPUs
  284.  
  285.          The file TOTBUILD.PAS is an "empty" file which USES all the Toolkit
  286.          units. Its sole purpose is to provide an easy way of re-compiling the
  287.          Toolkit units.
  288.          If you ever need to rebuild all the TPUs, load the TOTBUILD.PAS file
  289.          from the C:\TURBO\TOT directory (or wherever you installed the source
  290.          files), and select Compile Build. If the program does not successfully
  291.          compile, refer to the problems section at the end of chapter 2.
  292.  
  293.  
  294.  
  295. Compiler Directives
  296.          Every unit in the Toolkit has an include statement to include the file
  297.          TOTFLAGS.INC. This file is designed to specify all the common compiler
  298.          directives that you want to apply to every unit in your program.
  299.  
  300.          The compiler directives added to your main program apply only to that
  301.          module and not to any of the units used by the program. So if you
  302.          wanted to ensure that a specific compiler directive is operative in
  303.          every unit, you would have to edit every unit source code file and add
  304.          the appropriate directive. (Yes, you could add them to the IDE options
  305.          menu, but if you work on multiple projects, you would have to keep
  306.          swapping the directives in and out as necessary.)
  307.          Whenever you develop a program using the Toolkit, you should add an
  308.          include directive to your main program and any other units you develop,
  309.          as follows:
  310.  
  311.                   {$I TOTFLAGS.INC}
  312.  
  313.          Any compiler directives you set in the file TOTFLAGS.INC file will then
  314.          affect your code and the Toolkit code.
  315.  
  316.  
  317.  
  318. Toolkit Basics                                                               3-7
  319. --------------------------------------------------------------------------------
  320.  
  321.          The TOTFLAGS.INC file contains a host of standard Turbo Pascal compiler
  322.          directives which are controlled with four special compiler directives:
  323.          FINAL, OVERLAY, FLOAT and FLOATEM. These four compiler directives are
  324.          located at the top of the file in an enabled or disabled state. For
  325.          example, in the disabled state the $DEFINE directive is broken up with
  326.          spaces, e.g.
  327.  
  328.                     { $ DEFINE OVERLAY}
  329.  
  330.          To activate a directive simply remove the leading spaces, e.g.
  331.  
  332.                     {$DEFINE OVERLAY}
  333.  
  334.          To disable the directive again just put the spaces back!
  335.  
  336.          The four compiler directives have a significant impact on the final
  337.          program code, and are discussed in detail below.
  338.  
  339.  
  340. FINAL
  341.          During program development it is a good idea to switch on range check-
  342.          ing and stack checking, etc. These directives keep you honest and
  343.          reduce the likelihood of a machine "hang" or lock-up. For example, if
  344.          you try to assign a value of 300 to a byte, the compiler will identify
  345.          the problem before it goes too far. The bad news is that programs
  346.          compiled in the check everything state tend to be slower and larger
  347.          than their carefree brethren. So, once you have debugged and tested
  348.          your program and you are confident that the checking is no longer nec-
  349.          essary, you should switch off the appropriate directives.
  350.  
  351.          The FINAL compiler directive is designed to simplify this task. During
  352.          program development, you should disable the FINAL compiler directive,
  353.          and then enable it when you are ready to build and distribute your
  354.          production program.
  355.          At the time of printing, the following compiler directives are
  356.          influenced by the FINAL directive:
  357.  
  358.          FINAL enabled        {$S-} no stack checking
  359.                               {$R-} no range checking
  360.                               {SD-} no debug information
  361.                               {$L-} no local symbols
  362.          FINAL disabled       {$S+} stack checking on
  363.                               {$R+} range checking on
  364.                               {SD+} debug information on
  365.                               {$L+} local symbols on
  366.  
  367.  
  368.  
  369. 3-8                                                                 User's Guide
  370. --------------------------------------------------------------------------------
  371.  
  372.          When FINAL is disabled, another Toolkit directive is defined: CHECK.
  373.          When CHECK is enabled, the Toolkit uses some additional code to check
  374.          parameters passed to methods. For example, in the WINOBJ method
  375.          SetSize, a check is made to ensure the window coordinates fit on the
  376.          screen. When the FINAL directive is enabled, CHECK is automatically
  377.          disabled to reduce program size. If a program runs fine until you set
  378.          the FINAL directive, check the parameters you are using in the problem
  379.          area of the code.
  380.  
  381.          Remember that if you want to use the IDE or stand alone debugger on
  382.          your application, you must disable the FINAL directive.
  383.  
  384.  
  385. OVERLAY
  386.  
  387.          Any of the Toolkit units can be overlaid.
  388.          Turbo Pascal requires that all overlaid units include a {$O+} compiler
  389.          directive, and that all methods, procedures and functions use the far
  390.          call method, i.e. they are compiled in the {$F+} state. By activating
  391.          the {$DEFINE OVERLAY} statement in the TOTFLAGS.INC file, all the Tool-
  392.          kit units will be compiled in the {$F+,O+} state.
  393.  
  394.          It is important to note that Turbo Pascal imposes an important restric-
  395.          tion on an overlaid unit - there must be no initialization statements
  396.          at the end of the unit. Every Toolkit unit has an initialization
  397.          procedure, and this procedure name is consistently the unit name minus
  398.          the TOT prefix plus the characters "INIT". For example, the initializa-
  399.          tion procedures for the TOTFAST and TOTSYS units are FASTINIT and SYSI-
  400.          NIT, respectively.
  401.          IMPORTANT: When the OVERLAY compiler directive is activated, you must
  402.          call each overlay unit's INIT procedure as the first statements in your
  403.          main program.
  404.  
  405.          Listed below is a small demo program, DEMOV1.PAS, which is an overlaid
  406.          version of the DEMMS1.PAS file reviewed earlier.
  407.               program DemoOverlay1;
  408.               {demov1.pas - make sure the OVERLAY compiler directive
  409.               is enabled in the TOTFLAGS.INC file before compiling}
  410.  
  411.               {$I TOTFLAGS.INC}
  412.               Uses OVERLAY, DOS, CRT,
  413.                    totSYS, totLOOK, totINPUT, totFAST, totWIN, totIO1, totMSG;
  414.  
  415.               {$O totSYS}
  416.               {$O TOTLOOK}
  417.               {$O totINPUT}
  418.               {$O totFAST}
  419.  
  420.  
  421.  
  422. Toolkit Basics                                                               3-9
  423. --------------------------------------------------------------------------------
  424.  
  425.               {$O totWIN}
  426.               {$O totIO1}
  427.               {$O totMSG}
  428.  
  429.               Var
  430.                  MsgWin : MessageOBJ;
  431.               begin
  432.                  OvrInit('DEMOV1.OVR');{initialize the overlay}
  433.                  OvrInitEMS;
  434.                  SYSInit;          {initialize the Toolkit units}
  435.                  LOOKInit;
  436.                  INPUTInit;
  437.                  FASTInit;
  438.                  WINInit;
  439.                  IO1Init;
  440.                  MSGInit;
  441.                  Screen.Clear(white,'░'); {paint the screen}
  442.                  with MsgWin do
  443.                  begin
  444.                     Init(1,' Message ');
  445.                     AddLine('');
  446.                     AddLine('The message unit provides a');
  447.                     AddLine('very easy way of displaying');
  448.                     AddLine('pop-up messages in a move-');
  449.                     AddLine('able window.');
  450.                     AddLine('');
  451.                     Show;
  452.                     Done;
  453.                  end;
  454.               end.
  455.  
  456.  
  457.          Note that all the units used directly or indirectly by the totMSG unit
  458.          are used and the appropriate INIT procedure is called. The order of the
  459.          INIT procedure calls is important. If you are using any Toolkit units
  460.          which write to the screen and poll the keyboard, then you should, as a
  461.          minimum, call the following procedures in the specified order:
  462.                SYSInit;
  463.                LOOKInit;
  464.                INPUTInit;
  465.                FASTInit;
  466.                WINInit;
  467.  
  468.          If you execute the DEMOV1 program you will notice it is unbearably
  469.          slow! As the demo ably illustrates, you should not overlay the primary
  470.          Toolkit units totSYS, totINPUT, and totFAST. Routines from these units
  471.          are called very frequently, and placing them in overlays will really
  472.          slooooow your application down. DEMOV2.PAS, listed below, is a more
  473.          practical overlay solution:
  474.  
  475.  
  476. 3-10                                                                User's Guide
  477. --------------------------------------------------------------------------------
  478.  
  479.                program DemoOverlay2;
  480.                {demov2 - make sure the OVERLAY compiler directive
  481.                 is enabled in the TOTFLAGS.INC file before compiling}
  482.  
  483.                {$I TOTFLAGS.INC}
  484.                Uses OVERLAY, DOS, CRT,
  485.                     totSYS, totLOOK, totINPUT, totFAST, totWIN, totIO1, totMSG;
  486.  
  487.                {$O totWIN}
  488.                {$O totIO1}
  489.                {$O totMSG}
  490.                Var
  491.                   MsgWin : MessageOBJ;
  492.  
  493.                begin
  494.                   OvrInit('DEMOV2.OVR');{initialize the overlay}
  495.                   OvrInitEMS;
  496.                   SYSInit;         {initialize the Toolkit units}
  497.                   LOOKInit;
  498.                   INPUTInit;
  499.                   FASTInit;
  500.                   WINInit;
  501.                   IO1Init;
  502.                   MSGInit;
  503.                   Screen.Clear(white,'░'); {paint the screen}
  504.                   with MsgWin do
  505.                   begin
  506.                      Init(1,' Message ');
  507.                      AddLine('');
  508.                      AddLine('The message unit provides a');
  509.                      AddLine('very easy way of displaying');
  510.                      AddLine('pop-up messages in a move-');
  511.                      AddLine('able window.');
  512.                      AddLine('');
  513.                      Show;
  514.                      Done;
  515.                   end;
  516.                end.
  517.  
  518.          In this example, only the three units totWIN, totIO1 and totMSG are
  519.          overlaid, and performance is almost as good as a non-overlaid version.
  520.          It is important to note the OVERLAY compiler directive disables all the
  521.          Toolkit initialization procedures regardless of whether each unit is
  522.          actually overlaid or not. For this reason, the second demo still ini-
  523.          tializes all of the Toolkit units. Refer to the Flash cards for a list
  524.          of unit dependencies, i.e. which files to INIT when you use a unit.
  525.  
  526.  
  527.  
  528. Toolkit Basics                                                              3-11
  529. --------------------------------------------------------------------------------
  530.  
  531.          Finally, if you are new to overlays, don't forget that the overlay file
  532.          (.OVR) can be combined back into the EXE file using the following DOS
  533.          command:
  534.  
  535.                   COPY/B progname.EXE + progname.OVR
  536.          The OvrInit procedure must initialize the overlay file from the EXE
  537.          file, and this can be achieved with the following command:
  538.  
  539.                   OvrInit(ParamStr(0));
  540.  
  541.  
  542. FLOAT
  543.  
  544.          Turbo Pascal and the Toolkit support extended reals. By default, Turbo
  545.          Pascal uses six byte reals, but using compiler directives high preci-
  546.          sion Single, Double, Extended and Comp reals can be used.
  547.          If you want to use the higher precision reals, activate the FLOAT com-
  548.          piler directive. The Toolkit will automatically set the necessary Turbo
  549.          Pascal compiler directives. When FLOAT is enabled, the Toolkit supports
  550.          all real types. When FLOAT is disabled, all the real types are type-
  551.          cast to the base REAL type. In other words, the types SINGLE, DOUBLE,
  552.          EXTENDED and COMP appear to the compiler as plain old REAL. This
  553.          type-casting is performed in the small totREAL unit.
  554.  
  555.          If the software compiled in the FLOAT state is to be run on a computer
  556.          without a math co-processor, the FLOATEM compiler directive (discussed
  557.          next) must also be enabled. Note that the totSYS unit provides an
  558.          object for checking the presence of a math co-processor.
  559.  
  560.  
  561. FLOATEM
  562.  
  563.          Turbo Pascal is capable of emulating an 8087 math co-processor if the
  564.          PC does not have one installed. Enable the FLOAT and FLOATEM (short for
  565.          float emulation) directives if you want to use high precision reals on
  566.          PCs with no math co-processor.
  567.          Note that the use of FLOATEM will increase the size of the program,
  568.          because Turbo Pascal links in the 8087 emulation code. Only use this
  569.          directive when necessary.
  570.  
  571.  
  572.  
  573. Using Standard Objects
  574.          Virtually all programs built with the Toolkit perform some basic tasks
  575.          such as writing to the screen and polling the keyboard. The Toolkit
  576.          provides a number of object instances (i.e. object variables) that are
  577.          automatically initialized when you use the related unit. For example,
  578.          the totFAST unit includes an instance of a ScreenOBJ called SCREEN.
  579.  
  580.  
  581.  
  582. 3-12                                                                User's Guide
  583. --------------------------------------------------------------------------------
  584.  
  585.          Listed below are each of the instances which provide the basic program-
  586.          ming facilities:
  587.  
  588.          SCREEN           The SCREEN instance is of type ScreenOBJ and is
  589.                           declared in the totFAST unit. SCREEN should be used
  590.                           for all writing to the screen. For more details, refer
  591.                           to chapter 5: Writing to the Screen.
  592.          MOUSE            The MOUSE instance is of type MouseOBJ and is declared
  593.                           in the totINPUT unit. The primary purpose of MOUSE is
  594.                           to provide a convenient way of controlling the mouse
  595.                           cursor. The methods HIDE and SHOW control whether the
  596.                           mouse is visible, and the method function VISIBLE
  597.                           returns true if the mouse is on display. Note that the
  598.                           Toolkit automatically hides the mouse while screen
  599.                           writing occurs. For further information, refer to
  600.                           chapter 6: Keyboard and Mouse Input.
  601.  
  602.          KEY              The KEY instance is of type KeyOBJ and is also
  603.                           declared in the totINPUT unit. This instance provides
  604.                           all the methods for accessing the user's keyboard and
  605.                           mouse input. The main method is Getkey, which waits
  606.                           for the user to press a key or click a mouse button.
  607.                           More details are described in chapter 6.
  608.          MONITOR^         The MONITOR instance is a pointer to a DisplayOBJ and
  609.                           is declared in the totSYS unit. MONITOR^ can be used
  610.                           to ascertain the width and depth of the display, as
  611.                           well as set condensed mode display on or off. Refer to
  612.                           chapter 4: Determining and Controlling Hardware for
  613.                           more information.
  614.  
  615.  
  616.  
  617. Controlling a Program's Look & Feel
  618.          As well as the global instances described in the last section, the
  619.          Toolkit includes a variety of object instances which can be used to
  620.          control the overall look and feel of a program. For example, the
  621.          SCROLLTOT^ instance controls the way that scroll bars are drawn.
  622.  
  623.          To change the look of your application, all you have to do is modify
  624.          the appropriate instance. To save data space, all these instances are
  625.          dynamically created on the heap and must be referenced with the pointer
  626.          symbol (^). For example, to call the SCROLLTOT method SetScrollChars,
  627.          you would use the following syntax:
  628.                   ScrollTOT^.SetScrollChars(....);
  629.  
  630.  
  631.  
  632. Toolkit Basics                                                              3-13
  633. --------------------------------------------------------------------------------
  634.  
  635.          Listed below is a full description of each global instance which con-
  636.          trols the look and feel of your application. All these instances are
  637.          automatically initialized by the Toolkit, and a set of more than
  638.          adequate defaults (!) are assigned.
  639.  
  640.          In addition to these instances, there is a byte variable LPTPORT, in
  641.          the totMISC unit, which is used to indicate the default printer port
  642.          (set to 0 for LPT1, 1 for LPT2, etc.).
  643.  
  644.  
  645.             Note: the Toolkit uses a single byte to indicate the display
  646.             attribute or color - that is, the foreground and background bytes
  647.             combined into a single attribute byte. The totFAST unit provides
  648.             three functions to help you manipulate color attributes. The CATTR
  649.             function is passed a foreground and background color and returns a
  650.             single combined attribute byte. The FATTR function is passed an
  651.             attribute byte and returns the foreground color component. The
  652.             BATTR function is passed an attribute byte and returns the back-
  653.             ground color component.
  654.  
  655.             For example, the expression CAttr(white,blue); returns the value of
  656.             31, and the expression FAttr(31) returns 15, which is white.
  657.  
  658.             In all, there are 256 different foreground and background color
  659.             combinations; the Flash Cards include a chart which details them
  660.             all.
  661.  
  662.             When assigning colors, be sure to check the Monitor^.ColorOn bool-
  663.             ean function method to determine whether the system is using a
  664.             color or a monochrome device.
  665.  
  666.  
  667.  
  668. LookTOT
  669.  
  670.          The unit totLOOK is designed specifically to provide you with an easy
  671.          way to change the overall cosmetic appearance of your programs. The
  672.          unit includes a single instance LookTOT which is a pointer to a LookOBJ
  673.          object. LookTOT controls the window, menu and list default display
  674.          characteristics. If you want to change the overall color and style of
  675.          your program, change the LookTOT settings, and these will be inherited
  676.          by the window, menu and list objects.
  677.          Listed below are the methods for setting the various defaults:
  678.  
  679.  
  680.          SetWindow(Border,Body,Icons,Title: byte);
  681.  
  682.  
  683.  
  684. 3-14                                                                User's Guide
  685. --------------------------------------------------------------------------------
  686.  
  687.          This method sets the display attributes for the window border (where
  688.          the box is drawn), the central part of the window, the close and zoom
  689.          characters, and the window title. The defaults depend on whether the
  690.          host PC is using a color or a monchrome display.
  691.  
  692.  
  693.          SetWinKeys(Move,Stretch,Zoom: word);
  694.          This method sets the values of the keys which will invoke the window
  695.          move, stretch and zoom commands. The defaults are [KEYCAP], [KEYCAP],
  696.          and [KEYCAP].
  697.  
  698.  
  699.          SetListKeys(Endkey,Esc,Toggle,Tag,UnTag: word);
  700.          SetListKeys sets the values of the keys which are used with a ListOBJ
  701.          instance. The EndKey and Esc keys are used to remove the list window,
  702.          and the defaults are [KEYCAP] and [KEYCAP]. The Toggle key is used to
  703.          select or deselect individual items in the list and the default is the
  704.          [KEYCAP]. The Tag and UnTag keys are used to globally select or dese-
  705.          lect all items in the list, and the defaults are [KEYCAP] and [KEYCAP].
  706.  
  707.  
  708.          SetListChars(LeftChar,RightChar,ToggleOnChar,ToggleOffChar:char);
  709.          Sets the display characters which are used to emphasize the highlighted
  710.          topic in a list, as well as the characters used to indicate whether an
  711.          item in a list is selected or not.
  712.  
  713.  
  714.          SetMenu(Bor,Tit,Icon,HiHot,HiNorm,LoHot,LoNorm,Off:byte)
  715.          Sets the display characteristics of the pop-up and pull-down menus. The
  716.          method is passed eight (count 'em) parameters to give you complete
  717.          control of all the menu display colors. The first three parameters set
  718.          the attribute of the menu window border, title and close icon. The next
  719.          four parameters specify the attributes for the highlighted and normal
  720.          menu items. (Each menu item may be displayed in two colors to emphasize
  721.          a specific letter or word.) The last parameter is the attribute for
  722.          non-selectable (i.e. turned-off) menu items.
  723.  
  724.  
  725.          SetDefaults;
  726.          Call this method with no parameters if you want to reset all the Look-
  727.          TOT settings to the Toolkit defaults.
  728.  
  729.  
  730.  
  731. Toolkit Basics                                                              3-15
  732. --------------------------------------------------------------------------------
  733.  
  734. ShadowTOT
  735.  
  736.          ShadowTOT is a pointer to an instance of type ShadowOBJ, and is
  737.          declared in the totFAST unit. ShadowTOT is used to control the size,
  738.          color and perspective of the shadows used by pop-up windows, lists,
  739.          menus and the like.
  740.          An enumerated type ShadowPosition is used to describe the shadow per-
  741.          spective, and the elements are defined as UpLeft, UpRight, DownLeft,
  742.          and DownRight. Shadows can be set as see-through or solid characters,
  743.          the choice is yours! You can even set how wide and deep the shadow will
  744.          be.
  745.  
  746.          The following methods are used to set the shadow characteristics:
  747.  
  748.          SetShadowStyle(ShadP:ShadowPosition;ShadA:byte;ShadC:char);
  749.  
  750.          The first parameter indicates the direction of the shadow using a mem-
  751.          ber of the ShadowPosition enumerated type. The second parameter is the
  752.          display attribute of the shadow, and the third is the character used to
  753.          draw the shadow. If a space (' ') is passed, the shadow will be see-
  754.          through, otherwise the shadow will be drawn using the specified charac-
  755.          ter.
  756.  
  757.          SetShadowSize(ShadW,ShadD:byte);
  758.  
  759.          This method controls the size of the shadow. Pass the number of charac-
  760.          ters wide and deep that you want the shadow to be. If the width and
  761.          depth are set to zero, no shadows will be drawn.
  762.  
  763.          SetDefaults;
  764.  
  765.          Call this method with no parameters if you want to reset all the Shad-
  766.          owTOT settings to the Toolkit defaults.
  767.  
  768.          The following program, DEMSH1.PAS, illustrates how to change the shadow
  769.          settings, and figure 3.1 shows the resultant output when the program is
  770.          executed.
  771.  
  772.          program DemoShadow1;
  773.          {demsh1}
  774.          Uses DOS, CRT,
  775.               totFAST;
  776.  
  777.          begin
  778.             with Screen do
  779.             begin
  780.                Clear(white,'░'); {paint the screen}
  781.                ShadFillBox(3,3,20,8,31,1);
  782.                ShadowTOT^.SetShadowStyle(Upleft,lightgray,' ');
  783.  
  784.  
  785. 3-16                                                                User's Guide
  786. --------------------------------------------------------------------------------
  787.  
  788.                ShadFillBox(3,12,20,19,47,2);
  789.                ShadowTOT^.SetShadowStyle(Downleft,lightblue,' ');
  790.                ShadowTOT^.SetShadowSize(4,1);
  791.                ShadFillBox(35,2,70,10,94,3);
  792.                ShadowTOT^.SetShadowStyle(DownLeft,white,'!');
  793.                ShadFillBox(40,13,60,18,15,4);
  794.                ShadowTOT^.SetDefaults;
  795.                ShadFillBox(5,21,75,23,78,5);
  796.             end; {with}
  797.          end.
  798.  
  799.  
  800.  
  801. Figure 3.1                                                              [SCREEN]
  802. The Shadow Demo
  803. Program
  804.  
  805.  
  806.  
  807. ScrollTOT
  808.          ScrollTOT is a pointer to an instance of type ScrollOBJ, and is
  809.          declared in the totFAST unit. ScrollTOT is used to control the charac-
  810.          ters used to build the scroll bars displayed in scrolling windows.
  811.  
  812.          There are basically four different characters used to create a scroll
  813.          bar. There is the directional arrow at each end, the background charac-
  814.          ter, and the elevator (or slider) character. These characters are con-
  815.          trolled with the following two methods:
  816.  
  817.          SetScrollChars(U,D,L,R,E,B:char);
  818.  
  819.          These six parameters represent the up and down directional arrows on
  820.          vertical scroll bars, the left and right directional arrows on horizon-
  821.          tal scroll bars, the elevator character and the background character.
  822.  
  823.          SetDefaults;
  824.  
  825.          Call this method with no parameters if you want to reset all the
  826.          ScrollTOT settings to the Toolkit defaults.
  827.  
  828.  
  829.          ScrollTOT does not affect the display attributes of the scroll bars.
  830.          The window border attribute is normally used.
  831.          SCREEN provides two methods for writing scroll bars anywhere on the
  832.          display: WriteHScrollBar, WriteVScrollBar. Refer to Chapter 5 for fur-
  833.          ther information.
  834.  
  835.  
  836.  
  837. Toolkit Basics                                                              3-17
  838. --------------------------------------------------------------------------------
  839.  
  840. IOTOT
  841.  
  842.          Using consistent color schemes is particularly important during full-
  843.          screen input. The totIO1 unit includes IOTOT which is designed to con-
  844.          trol all the IO display attributes. IOTOT is a pointer to an object of
  845.          type InputOBJ. The uses of IOTOT are discussed in detail in chapter 11.
  846.  
  847.  
  848. FmtNumberTOT
  849.  
  850.          The totIO2 unit provides routines for the input of REAL and INTEGER
  851.          values. These values can be optionally formatted when the user moves to
  852.          the next field, i.e. when the user is editing, the number is unfor-
  853.          matted, but when the user exits the field, the number can be formatted
  854.          in a variety of styles. For example, the number 123456.78 might be
  855.          formatted as $123,456.78.
  856.          The totIO2 unit includes FmtNumberTOT, a pointer to an object instance
  857.          of type FmtNumberOBJ. This instance defines the default formatting that
  858.          will be applied to real and integer fields during full-screen input.
  859.          Any of the format defaults can be overridden for individual fields.
  860.          Field formatting is discussed in detail in chapter 11: Controlling User
  861.          Input.
  862.  
  863.  
  864.  
  865. DateTOT
  866.          The totDATE unit provides functions for manipulating and converting
  867.          Julian and Gregorian dates. A number of default values, e.g. the char-
  868.          acter used to separate the month from the day and the year (like '  /
  869.          /  '), are defined in DateTOT, a pointer to an object instance of type
  870.          DateOBJ. These defaults are used in both the totDATE and totIO2 units.
  871.          Refer to chapter 13: Managing Dates for further details.
  872.  
  873.  
  874.  
  875. AlphabetTOT
  876.          The totINPUT unit includes the object AlphabetOBJ for managing upper-
  877.          and lower-case characters, and the global instance AlphabetTOT is a
  878.          pointer to an AlphabetOBJ object.
  879.  
  880.          AlphabetTOT controls how the Toolkit determines/changes the case of
  881.          alpha-characters. It is designed for international Toolkit users who
  882.          want to use a non-English alphabet. If you are writing "English-
  883.          speaking" programs, you do not need to tamper with this object.
  884.          The object contains a list of all valid upper-case letters, lower-case
  885.          letters and punctuation characters. The totLOOK unit includes the type
  886.          declaration CharSet, which is equal to a set of char. Some methods are
  887.  
  888.  
  889.  
  890. 3-18                                                                User's Guide
  891. --------------------------------------------------------------------------------
  892.  
  893.          passed a parameter of type CharSet. You may specify multiple characters
  894.          and/or ranges of characters, provided that they are enclosed in square
  895.          brackets []. For example, the following expressions are valid CharSets:
  896.  
  897.                     ['a','b','f'..'z']
  898.                     ['A'..'Z',#129..#148]
  899.                     ['a'..'z']
  900.                     [',','.']
  901.          AlphabetTOT methods can be called using the syntax AlphabetTOT^.method,
  902.          and the following methods are supported:
  903.  
  904.  
  905.          SetUpper(Letters:CharSet);
  906.          Defines which characters comprise the upper-case alphabet. The method
  907.          is passed one parameter of type CharSet, e.g. SetUpper(['A'..'Z']);.
  908.  
  909.  
  910.          SetLower(Letters:CharSet);
  911.          Defines which characters comprise the lower-case alphabet. The method
  912.          is passed one parameter of type CharSet, e.g. SetLower(['a'..'z']);.
  913.  
  914.  
  915.          SetPunctuation(Letters:CharSet);
  916.          Defines which characters are used in normal punctuation. The method is
  917.          passed one parameter of type CharSet, e.g. SetPunctua-
  918.          tion([',',';','.',':',' ']);.
  919.  
  920.  
  921.          IsUpper(K:word): boolean;
  922.          This function method is passed one parameter, representing the ordinal
  923.          value of a character, and returns true if the character is listed in
  924.          the upper-case alphabet, e.g. IsUpper(ord('A'));.
  925.  
  926.  
  927.          IsLower(K:word): boolean;
  928.          This function method is passed one parameter, representing the ordinal
  929.          value of a character, and returns true if the character is listed in
  930.          the lower-case alphabet, e.g. IsLower(107);.
  931.  
  932.  
  933.          IsLetter(K:word): boolean;
  934.          This function method is passed one parameter, representing the ordinal
  935.          value of a character, and returns true if the character is listed in
  936.          either the upper- or lower-case alphabet.
  937.  
  938.  
  939.          IsPunctuation(K:word): boolean;
  940.  
  941.  
  942.  
  943. Toolkit Basics                                                              3-19
  944. --------------------------------------------------------------------------------
  945.  
  946.          This function method is passed one parameter, representing the ordinal
  947.          value of a character, and returns true if the character is listed as a
  948.          punctuation character.
  949.  
  950.  
  951.  
  952.          On occasion, the Toolkit needs to convert the case of alpha characters.
  953.          To accommodate international users, the Toolkit uses AlphabetTOT to
  954.          convert character case, rather than rely on the English-specific rou-
  955.          tines provided with Turbo Pascal. The Toolkit calls the following two
  956.          methods to convert character case:
  957.  
  958.  
  959.          GetUpCase(Ch:char):char;
  960.          This method is passed a character, and returns the upper-case equiva-
  961.          lent of the character.
  962.  
  963.  
  964.          GetLoCase(Ch:char):char;
  965.          This method is passed a character, and returns the lower-case equiva-
  966.          lent of the character.
  967.  
  968.  
  969.          You can control precisely how characters are converted by creating your
  970.          own conversion routines. All you have to do is create two functions
  971.          following some specific rules, and then call the methods Alphabet-
  972.          TOT^.AssignUpCaseFunc and AlphabetTOT^.AssignLoCaseFunc to instruct the
  973.          Toolkit to use your functions.
  974.          For a function to be eligible as a character case converter it must
  975.          adhere to the following three rules:
  976.  
  977.          Rule 1     The function must be declared as a FAR function. This can be
  978.                     achieved by preceding the function with a {$F+} compiler
  979.                     directive, and following the function with a {$F-} direc-
  980.                     tive. Alternatively, Turbo 6 users can use the new keyword
  981.                     FAR following the procedure statement.
  982.          Rule 2     The function must be declared with one passed parameter of
  983.                     type char, and it must return a char.
  984.  
  985.          Rule 3     The function must be at the root level, i.e. the function
  986.                     cannot be nested within another procedure or function.
  987.          The following function declaration follows these rules:
  988.  
  989.                   {$F+}
  990.                   function MyUpConverter(Ch:char):char;
  991.                   .....{statements}
  992.                   end;
  993.                   {$F-}
  994.  
  995.  
  996.  
  997. 3-20                                                                User's Guide
  998. --------------------------------------------------------------------------------
  999.  
  1000.          Internally, these functions should check the value of the passed char-
  1001.          acter, and return the character converted to the appropriate case. If
  1002.          the character is not suited to conversion, e.g. '1', simply return the
  1003.          character that was passed. Once you have created two functions (one for
  1004.          upper-case conversion and one for lower-case conversion), you should
  1005.          call the following assignment methods to instruct AlphabetTOT to use
  1006.          your routines:
  1007.  
  1008.  
  1009.          AssignUpCaseFunc(Func:CaseFunc);
  1010.          This method is passed the name of the function used to convert charac-
  1011.          ters to upper case. The procedure must adhere to the rules outlined
  1012.          above.
  1013.  
  1014.  
  1015.          AssignLoCaseFunc(Func:CaseFunc);
  1016.          This method is passed the name of the function used to convert charac-
  1017.          ters to lower case. The procedure must adhere to the rules outlined
  1018.          above.
  1019.  
  1020.  
  1021.          In summary, AlphabetTOT provides you with complete control over how the
  1022.          Toolkit determines and changes the case of alpha characters.
  1023.  
  1024.  
  1025. Program Size
  1026.  
  1027.          A constant battle during the development of the Toolkit was to minimize
  1028.          the size of programs developed with the Toolkit. A valid criticism of
  1029.          OOP is that it tends to swell the final program size, which makes it a
  1030.          subject of concern to most developers (that's you folks).
  1031.          With a hierarchical object organization even small applications tend to
  1032.          attract a high code overhead. However, the more features of the Toolkit
  1033.          you use, the more efficient your program will be. For example, listed
  1034.          below are the EXE file sizes of three of the demo programs:
  1035.  
  1036.                 DemFM8           114k
  1037.                 DemDR1           92k
  1038.                 DemMS1           56k
  1039.          The combined file size of the three programs is 262k. However, if these
  1040.          three examples are combined into a single example, the file size is
  1041.          actually 141k. The reason for the reduction is that each of the small
  1042.          programs uses common routines which can be shared in the combined
  1043.          program.
  1044.  
  1045.  
  1046.  
  1047. Toolkit Basics                                                              3-21
  1048. --------------------------------------------------------------------------------
  1049.  
  1050.          In real life, your fledgling program will start out bigger than you
  1051.          expected, but it will grow much less than anticipated as your program
  1052.          expands. Remember that compiler directives have a significant impact on
  1053.          program size, and you should enable the FINAL compiler directive for
  1054.          the production build of your application.
  1055.  
  1056.          If EXE file size is your concern, rather than code size, consider com-
  1057.          pressing the EXE file with a compression utility like PKlite from
  1058.          PKWare, Inc., or LZEXE by Fabrice Bellard.
  1059.